﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Data;
using System.Windows;
using System.Windows.Input;
using System.Windows.Shapes;
using System.Windows.Controls;
using Shoozla.View;
using Shoozla.DataModel;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Threading.Tasks;
using Shoozla.DataModel.Helper;


namespace Shoozla.ViewModel
{
    /// <summary>
    /// The ViewModel for the application's main window.
    /// </summary>
    public class MainWindowViewModel : ViewModelBase
    {
        public event FolderAddedDelegate FolderAdded;
        public delegate void FolderAddedDelegate(string folderName);

        #region Commands       
       
        private RelayCommand _CmdStopThreads;
        public RelayCommand CmdStopThreads
        {
            get
            {
                if (_CmdStopThreads == null)
                {
                    _CmdStopThreads = new RelayCommand(param => DoCmdStopThreads(), param =>
                    {
                        if (App.CurrentAppStatus != App.AppStatus.Idle) return true;
                        else return false;
                    });
                }
                return _CmdStopThreads;
            }
        }

        private RelayCommand _CmdSave;
        public RelayCommand CmdSave
        {
            get
            {
                if (_CmdSave == null)
                {
                    _CmdSave = new RelayCommand(param => DoCmdSave(), param => {
                        if (App.CurrentAppStatus == App.AppStatus.Idle && App.IsCollectionDirty()) return true;
                        else return false;
                        });
                }
                return _CmdSave;
            }
        }

        private RelayCommand _CmdSearch;
        public RelayCommand CmdSearch
        {
            get
            {
                if (_CmdSearch == null)
                {
                    _CmdSearch = new RelayCommand(param => DoCmdSearch(), param => CanExecuteSearch());
                }
                return _CmdSearch;
            }
        }

        private RelayCommand _CmdOpenFolder;
        public RelayCommand CmdOpenFolder
        {
            get
            {
                if (_CmdOpenFolder == null)
                {
                    _CmdOpenFolder = new RelayCommand(param => DoCmdOpenFolder(), param => CanExecuteUI());
                }
                return _CmdOpenFolder;
            }
        }

        private RelayCommand _CmdAbout;
        public RelayCommand CmdAbout
        {
            get
            {
                if (_CmdAbout == null)
                {
                    _CmdAbout = new RelayCommand(param => DoCmdAbout(), param => { return true; });
                }
                return _CmdAbout;
            }
        }

        private RelayCommand _CmdOpenLog;
        public RelayCommand CmdOpenFLog
        {
            get
            {
                if (_CmdOpenLog == null)
                {
                    _CmdOpenLog = new RelayCommand(param => DoCmdOpenFLog(), param => { return true; });
                }
                return _CmdOpenLog;
            }
        }

        private RelayCommand _cmdOpenList;
        public ICommand CmdOpenList {
            get {
                if (_cmdOpenList == null)
                {
                    _cmdOpenList = new RelayCommand(param => DoCmdOpenList(), param => CanExecuteUI());
                }
                return _cmdOpenList;
            }
        }

        private DirectoryInfo _currentFolder;
        public DirectoryInfo RootFolder
        {
            get { return _currentFolder; }
            set {
                if (value != _currentFolder)
                {
                    _currentFolder = value;
                    OnPropertyChanged("CurrentFolder");
                    OnPropertyChanged("FilesRead");
                    //OnPropertyChanged("Mp3Read");
                }
            }
        }

        //public int FilesRead
        //{
        //    get
        //    {
        //        if (RootFolder == null) return 0;
        //        else
        //        {
        //            FileInfo[] files = RootFolder.GetFiles("*.*", SearchOption.AllDirectories);
        //            return files.Count();
        //        }
        //    }
        //}


        #endregion

        #region Constructor

        public MainWindowViewModel()
        {
          //  base.DisplayName = Strings.MainWindowViewModel_DisplayName;
            base.DisplayName = "Shoozla Main Window";
            DoCmdOpenList();
        }

        #endregion // Constructor

        #region Do Commands

        private void DoCmdStopThreads()
        {
            App.StopWorkingThreads();
        }

        //+ Save all the modified mp3 files
        private void DoCmdSave()
        {
            if (App.AllItems != null)
            {
                var modifiedSongs = (
                        from m in App.AllItems
                        where m.Dirty
                        select m
                    );

                RaiseItemOperationStarted(modifiedSongs.Count(), "Saving covers");
                App.CurrentAppStatus = App.AppStatus.ApplyingCovers;
                
                Task backgroundFileWriterTask = Task.Factory.StartNew(() =>
                {
                    ParallelOptions paralleSettings = new ParallelOptions();
                    paralleSettings.CancellationToken = App.MainCancellationTokenSource.Token;
                    paralleSettings.MaxDegreeOfParallelism = ThreadHelper.CalculateTreads(modifiedSongs.Count(), ThreadingFactorEnum.Maximum);
                    //saving Mp3 in a parallel way
                    Parallel.ForEach<Mp3File>(modifiedSongs, paralleSettings, (song) =>
                    {
                    //foreach (Mp3File song in modifiedSongs)
                    //{
                        IMP3Processor mp3Processor = new IDSharpProcessor();
                        try
                        {
                            bool res = mp3Processor.SaveID3Tag(song);
                            if (res)
                            {
                                song.Dirty = false;
                                App.LogEntry("[SUCCESS] " + song + "  - Cover Saved");
                                RaiseFileSaved(song.FileName.FullName);
                            }
                        }
                        catch (Exception e)
                        {
                            App.LogEntry("[ERROR] Song not saved: " + e.Message);
                        }
                        finally { RaiseItemRead(); }

                        }); 
                    //}
                }, App.MainCancellationTokenSource.Token);

                backgroundFileWriterTask.ContinueWith((o) =>
                {
                    App.CurrentAppStatus = App.AppStatus.Idle;
                    _dispatcherUIThread.BeginInvoke(new Action(()=>{
                        RaiseItemOperationFinished();
                        System.Windows.MessageBox.Show(App.MainView,
                            App.Logger.FilesSaved + " files saved!", "Shoozla", MessageBoxButton.OK, MessageBoxImage.Information);
                            }));

                    }
                , App.MainCancellationTokenSource.Token);
            }
        }

        //+ Start the covers search
        private void DoCmdSearch()
        {           

            //it asks which "website" to use
            SearchAddinView saw = new SearchAddinView(App.MainView,SelectedItems.Count);
            var confirm = saw.ShowDialog();
            if (confirm != true)
                return;

            //start the internet search        
            App.LogEntry("Connecting to " + App.CoverSearcher.AddInName);

            if (App.CoverSearcher.Initialize())
            {
                //clean the logging
                App.Logger.CoversFound = 0;
                App.Logger.FilesProcessed = 0;
                App.Logger.FilesSaved = 0;

                //App.CoverImageCache.Reset();
                App.CoverSearcher.ClearCache();
                // RaiseItemOperationStarted(SelectedItems.Count, "Searching for multiple covers");
                ((CoverSearcher)App.CoverSearcher).CancelToken = App.MainCancellationTokenSource.Token;
                List<Mp3File> selected = SelectedItems.ToList<Mp3File>();
                Task backgroundSearcher = Task.Factory.StartNew(() =>
                {
                    App.CoverSearcher.FindMultipleCovers(selected, ThreadingFactorEnum.Maximum);
                }, App.MainCancellationTokenSource.Token);
            }
            else
                System.Windows.MessageBox.Show("Could not connect to the web service", "shoozla", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        private void DoCmdOpenList()
        {
            CurrentView = App.FolderView;
        }

        private void DoCmdOpenFLog()
        {
            App.Tracer.Flush();
            App.Tracer.Close();
            System.Diagnostics.Process.Start("notepad.exe", App.LogFileName);
        }

        private void DoCmdAbout()
        {
            AboutView aboutW = new AboutView();
            aboutW.ShowDialog();
        }

        private void DoCmdOpenFolder()
        {
            FolderBrowserDialog folderDialog = new FolderBrowserDialog();
            folderDialog.Description = "Select a folder with Mp3 files";
            var res = folderDialog.ShowDialog();
            if (res == DialogResult.OK)
            {
                if (FolderAdded != null)
                    FolderAdded.Invoke(folderDialog.SelectedPath);
               
            }
        }
        #endregion

        private bool CanExecuteSearch()
        {
            if (App.CurrentAppStatus == App.AppStatus.Idle && CanExecuteSelectedItemsOp())
                return true;
            else
                return false;
        }
    }
}